/*
 * 百度在线网络技术（北京）有限公司拥有本软件版权2022并保留所有权利。
 * Copyright 2022, Baidu.com,Inc 2:Baidu Online Network Technology (Beijing) Co.,Ltd,
 * All rights reserved.
 */

package com.azdebugit.suanfa.test.huawei;
//找出字符串数组的最长公共前缀
//如果不存在公共前缀，返回空字符串 ""。
public class LongestCommonPrefix {
    public static void main(String[] args) {
        String[] strs = {"flower","flow", "flight"};
        //测试思路1
        //String res = longestCommonPrefix(strs);

        //测试思路2
        //String res = longestCommonPrefix02(strs);

        //测试思路3
        String res = longestCommonPrefix02(strs);
        System.out.println(res);

    }

    //思路1：遍历字符串数组，先找出前两个的最长公共前缀，再以这个前缀和第三个字符串匹配找出他们的最长公共前缀，以此类推-->横向比较
    public static String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return new String("");
        }
        if (strs.length == 1) {
            return strs[0];
        }

        int length = strs.length;
        String prefix = strs[0];//默认最长公共前缀为第一个字符串
        for(int i  = 1; i < length; i ++) {
            prefix = longestCommonPrefix(prefix, strs[i]);//每次都以上一次得到的最长公共前缀和下一个字符串匹配
            //如果当前最长公共前缀为 "" 则没有必要再进行
            if ( prefix.length() == 0 ) {
                break;
            }
        }

        return prefix;
    }

    //前缀,重载
    public static String longestCommonPrefix(String str1, String str2) {
        int length = Math.min(str1.length(), str2.length());
        int index = 0;
        while (index < length && str1.charAt(index) == str2.charAt(index)) {
            index ++;
        }

        //返回两个字符串的最长公共前缀
        return str1.substring(0,index);
    }

    //思路2：纵向比较,从第0列开始比较每一个字符串的相同列字符是否相等
    public static String longestCommonPrefix02(String[] strs) {
        if (strs == null || strs.length == 0) {
            return new String("");
        }
        if (strs.length == 1) {
            return strs[0];
        }

        int cols = strs[0].length();
        int length = strs.length;

        for(int i = 0; i < cols; i ++) {
            char c = strs[0].charAt(i);//第 i 列
            for(int j = 1; j < length; j ++) {//比较每一个字符串的每一列
                //如果已经匹配到一个字符串的末尾或者有一个不相等，就得到了最长公共前缀
                if (i == strs[j].length() || c != strs[j].charAt(i)) {
                    return strs[0].substring(0,i);
                }
            }
        }

        //进行到这里，说明strs[0] 是后面的所有字符串的前缀
        return strs[0];
    }

    //思路3：分治法，根据思路1的思想，满足交换律
    public static String longestCommonPrefix03(String[] strs) {
        if (strs == null || strs.length == 0) {
            return new String("");
        }
        if (strs.length == 1) {
            return strs[0];
        }

        return longestCommonPrefix03(strs,0,strs.length - 1);

    }

    public static String longestCommonPrefix03(String[] strs, int start, int end) {
        if (start == end) {//不能再分
            return strs[start];
        } else {
            int mid = (start + end) / 2;
            String lcpLeft = longestCommonPrefix03(strs,start,mid);
            String lcpRight = longestCommonPrefix03(strs,mid + 1, end);
            return commonPrefix(lcpLeft,lcpRight);
        }
    }

    public static String commonPrefix(String str1, String str2) {
        int minLength = Math.min(str1.length(), str2.length());
        for(int i = 0; i < minLength; i ++) {
            if (str1.charAt(i) != str2.charAt(i)) {
                return str1.substring(0,i);
            }
        }

        return str1.substring(0,minLength);
    }
}

